﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Web;
using System.Net;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Xml.Serialization;
using System.ComponentModel;
using Microsoft.SharePoint;
using System.Security;

namespace Sukul.SharePoint.Common
{
    public class ServiceBase
    {

        #region [Singleton]
        private static ServiceBase _instance = null;
        private static object _lockObk = new object();
        public static ServiceBase Instance
        {
            get
            {
                lock (_lockObk)
                {
                    if (_instance == null)
                    {
                        _instance = new ServiceBase();
                    }
                }
                return ServiceBase._instance;
            }
        }
        #endregion

        public void CheckSecurity(string groupName)
        {
            if (SPContext.Current.Web.CurrentUser == null)
            {
                throw new SecurityException("You must be logged in to invoke this service");
            }
            //if (!string.IsNullOrEmpty(groupName))
            //{
            //    SPGroup group = null;
            //    try
            //    {
            //        group = SPContext.Current.Web.Groups[groupName];
            //    }
            //    catch { }
            //    if (group != null && !group.ContainsCurrentUser)
            //    {
            //        throw new SecurityException(string.Format("User {0} must be a member of the group '{1}' to invoke this service",
            //            SPContext.Current.Web.CurrentUser, groupName));
            //    }
            //}
            return;
        }

        public void AddResponseHeader()
        {
            OutgoingWebResponseContext Response = WebOperationContext.Current.OutgoingResponse;
            HttpResponseHeader cacheHeader = HttpResponseHeader.CacheControl;
            String cacheControlValue = String.Format("max-age={0}, must-revalidate", 1);
            Response.Headers.Add(cacheHeader, cacheControlValue);
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
        }

        public DTO.WebServiceRequest GetRequestObject(string request)
        {
            DTO.WebServiceRequest requestObj = null;
            if (!string.IsNullOrEmpty(request))
            {
                // JSON Serializer crashes the worker process. Replacing with DataContractJsonSerializer
                //sResponse = Newtonsoft.Json.JsonConvert.SerializeObject(response);
                requestObj = JSONDeserializeObject<DTO.WebServiceRequest>(request);
                //requestObj = Newtonsoft.Json.JsonConvert.DeserializeObject<DTO.WebServiceRequest>(request);

            }
            return requestObj;
        }


        /// Serializes an object to xml string.
        public string XMLSerialize(object o)
        {
            StringWriter output = new StringWriter(new StringBuilder());
            try
            {
                XmlSerializer ser = new XmlSerializer(o.GetType());
                ser.Serialize(output, o);
            }
            catch (Exception) { throw; }

            return output.ToString();
        }

        /// Deserializes an xml string into the equivalent object.
        public T XMLDeSerialize<T>(string xml)
        {
            XmlSerializer ser = new XmlSerializer(typeof(T));
            StringReader input = new StringReader(xml);
            return (T)ser.Deserialize(input);
        }

        public T GetAssemblyAttribute<T>(Assembly assembly) where T : Attribute
        {
            if (assembly == null) return null;
            object[] attributes = assembly.GetCustomAttributes(typeof(T), true);
            if (attributes == null) return null;
            if (attributes.Length == 0) return null;
            return (T)attributes[0];

        }

        public string JSONSerializeObject(object response)
        {
            string sResponse = string.Empty;
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(response.GetType());
            using (MemoryStream ms = new MemoryStream())
            {
                serializer.WriteObject(ms, response);
                sResponse = Encoding.Default.GetString(ms.ToArray());
            }
            return sResponse;
        }

        public string JSONSerializeObject(object response, IEnumerable<Type> knownTypes)
        {
            string sResponse = string.Empty;
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(response.GetType(), knownTypes);
            using (MemoryStream ms = new MemoryStream())
            {
                serializer.WriteObject(ms, response);
                sResponse = Encoding.Default.GetString(ms.ToArray());
            }
            return sResponse;
        }

        public T JSONDeserializeObject<T>(string request)
        {
            var requestO = default(T);
            if (!String.IsNullOrEmpty(request))
            {
                using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(request)))
                {
                    DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
                    requestO = (T)serializer.ReadObject(ms);
                }
            }
            return requestO;
        }

        public string HandleResponseError(DTO.WebServiceResponse response, Exception ex)
        {
            response.IsSuccess = false;
            response.ErrorMessage = ex.ToString();
            response.Payload = "No data";
            response.FriendlyErrorMessage = "An error occured in the business logic service.";
            response.ErrorStackTrace = ex.StackTrace;

            string responseString = string.Empty;
            try { responseString = ServiceBase.Instance.JSONSerializeObject(response); }
            catch { }

            return responseString;
        }

    }
}
